package com.demo2do.fms.admin.service.supplier.impl;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.demo2do.core.entity.exception.BusinessException;
import com.demo2do.core.entity.page.Page;
import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.persistence.annotation.Dao;
import com.demo2do.fms.admin.dao.authority.BranchDao;
import com.demo2do.fms.admin.dao.supplier.AppraisalResultDao;
import com.demo2do.fms.admin.dao.supplier.AppraisalTemplateItemDao;
import com.demo2do.fms.admin.dao.supplier.OrganizationDao;
import com.demo2do.fms.admin.dao.supplier.AppraisalResultItemDao;
import com.demo2do.fms.admin.entity.search.supplier.AppraisalResultSearch;
import com.demo2do.fms.admin.entity.security.Login;
import com.demo2do.fms.admin.service.DataServiceImpl;
import com.demo2do.fms.admin.service.supplier.AppraisalResultService;
import com.demo2do.fms.entity.appraisal.Appraisal;
import com.demo2do.fms.entity.appraisal.AppraisalResult;
import com.demo2do.fms.entity.appraisal.AppraisalResultItem;
import com.demo2do.fms.entity.appraisal.AppraisalTemplateItem;
import com.demo2do.fms.entity.appraisal.AppraisalType;
import com.demo2do.fms.entity.authority.Branch;
import com.demo2do.fms.entity.supplier.common.Supplier;
import com.demo2do.fms.entity.vendor.Vendor;

/**
 * @author houtao
 */
@Service("appraisalResultService")
public class AppraisalResultServiceImpl extends DataServiceImpl<AppraisalResult> implements AppraisalResultService {
    
    @Dao
    private AppraisalResultDao appraisalResultDao;
    
    @Dao
    private AppraisalTemplateItemDao appraisalItemTemplateDao;
    
    @Dao
    private OrganizationDao organizationDao;
    
    @Autowired
    private GenericDaoSupport genericDaoSupport;
    
    @Dao
    private AppraisalResultItemDao appraisalResultItemDao;
    
    @Dao
    private BranchDao branchDao;

    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#countByTarget(java.lang.String, com.demo2do.fms.admin.entity.security.Login)
     */
    public int countByTarget(String target, Login login) {
        
        if (login.isAdminUser() || login.isSuper()) {
            
            return appraisalResultDao.countByTarget(target);
            
        } else if (login.isBranchUser()) {
            
            Branch branch = branchDao.load(login.getBranch());
            return appraisalResultDao.countByTarget(target, branch);
            
        } else if (login.isSponsorUser() || login.isFmsUser()) {
            
            Supplier supplier = genericDaoSupport.load(Supplier.class, login.getSupplierId());
            if (supplier.isSecond()) {
                return 0;
            }
            return appraisalResultDao.countByTarget(target, supplier);
            
        } else {
            return 0;
        }
        
    }

    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#countByTarget(java.util.List)
     */
    public int countByTarget(List<String> supplierIds) {
        if (CollectionUtils.isEmpty(supplierIds)) {
            return 0;
        }
        return appraisalResultDao.countByTarget(supplierIds);
    }

    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#count(com.demo2do.fms.admin.entity.security.Login)
     */
    public int count(Login login) {
        
        if (!login.isSupplier()) {       // 总部用户 
            
            return appraisalResultDao.count();
            
        } else {                         // 供方用户
            
            String supplierId = String.valueOf(login.getSupplierId());
            return appraisalResultDao.countByTarget(supplierId);
            
        }
        
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#count(com.demo2do.fms.admin.entity.search.supplier.AppraisalResultSearch, com.demo2do.fms.admin.entity.security.Login)
     */
    public int count(AppraisalResultSearch search, Login login) {
        
        if (login.isSupplier()) {
            String target = String.valueOf(login.getSupplierId());
            search.setTarget(target);
        }
        
        String sentence = search.buildSentenceTemplate();
        Map<String, Object> parameters = search.buildParameters();
        return genericDaoSupport.count(sentence, parameters);
        
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#list(com.demo2do.fms.admin.entity.search.supplier.AppraisalResultSearch, com.demo2do.fms.admin.entity.security.Login, com.demo2do.core.entity.page.Page)
     */
    @SuppressWarnings("unchecked")
    public List<AppraisalResult> list(AppraisalResultSearch search, Login login, Page page) {
        
        if (login.isSupplier()) {
            String target = String.valueOf(login.getSupplierId());
            search.setTarget(target);
        }
        
        String sentence = search.buildSentenceTemplate();
        Map<String, Object> parameters = search.buildParameters();
        
        List<AppraisalResult> results = genericDaoSupport.searchForList(sentence, parameters, page.getBeginIndex(), page.getEveryPage());
        page.calculate();
        return results;
        
    }

    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultSerive#listByResult(java.util.List)
     */
    public List<AppraisalResultItem> listByResult(List<Long> resultIds) {
        return appraisalResultItemDao.listByResult(resultIds);
    }

    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#listByTarget(java.lang.String, com.demo2do.fms.admin.entity.security.Login)
     */
    public List<AppraisalResult> listByTarget(String target, Login login) {
        
        if (login.isAdminUser() || login.isSuper()) {
            
            return appraisalResultDao.listByTarget(target);
            
        } else if (login.isBranchUser()) {
            
            Branch branch = branchDao.load(login.getBranch());
            return appraisalResultDao.listByTarget(target, branch);
            
        } else if (login.isSponsorUser() || login.isFmsUser()) {
            
            Supplier supplier = genericDaoSupport.load(Supplier.class, login.getSupplierId());
            return appraisalResultDao.listByTarget(target, supplier);
            
        } else {
            return Collections.emptyList();
        }
        
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#listByTarget(java.lang.String, java.util.Date)
     */
    public List<AppraisalResult> listByTarget(String target, Date timeAgo) {
        return appraisalResultDao.listByTarget(target, timeAgo);
    }

    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#listByTarget(java.lang.String, com.demo2do.core.entity.page.Page)
     */
    public List<AppraisalResult> listByTarget(String target, Page page) {
        return appraisalResultDao.listByTarget(target, page.getBeginIndex(), page.getEveryPage());
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#listByTarget(java.util.List)
     */
    public List<AppraisalResult> listByTarget(List<String> targets) {
        return appraisalResultDao.listByTarget(targets);
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#list(com.demo2do.fms.admin.entity.security.Login, com.demo2do.core.entity.page.Page)
     */
    public List<AppraisalResult> list(Login login, Page page) {
        
        page.calculate();
        
        if (!login.isSupplier()) {      // 总部、分区用户
            
            return appraisalResultDao.list(page.getBeginIndex(), page.getEveryPage());
            
        } else {                        // 供方
            
            String supplierId = String.valueOf(login.getSupplierId());
            return appraisalResultDao.listByTarget(supplierId, page.getBeginIndex(), page.getEveryPage());
            
        }
        
    }

    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#list(com.demo2do.fms.entity.appraisal.Appraisal)
     */
    public List<AppraisalResult> list(Appraisal appraisal) {
        return appraisalResultDao.list(appraisal);
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#listTarget(com.demo2do.fms.entity.appraisal.Appraisal)
     */
    @SuppressWarnings("unchecked")
    public List<String> listTarget(Appraisal appraisal) {
        List<AppraisalResult> appraisalResults = appraisalResultDao.list(appraisal);
        return com.demo2do.core.utils.CollectionUtils.extractPropertyList(appraisalResults, "target");
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#listItem(com.demo2do.fms.entity.appraisal.Appraisal)
     */
    public List<AppraisalResultItem> listItem(Appraisal appraisal) {
        return appraisalResultItemDao.list(appraisal);
    }

    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#listItemResult(com.demo2do.fms.entity.appraisal.AppraisalResult)
     */
    public List<AppraisalResultItem> listItem(AppraisalResult appraisalResult) {
        return appraisalResultItemDao.list(appraisalResult);
    }

    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#create(com.demo2do.fms.entity.supplier.common.Supplier, com.demo2do.fms.entity.appraisal.Appraisal, java.lang.Long)
     */
    public void create(Supplier supplier, Appraisal appraisal, Long operator) {
        
        // 1. valid supplier whether exists
        AppraisalResult existAppraisalResult = appraisalResultDao.load(appraisal, supplier.getId().toString());
        if (existAppraisalResult != null) {
            throw BusinessException.newInstance("500", "供方'" + supplier.getName() + "'已存在本次绩效考核中");
        }
        
        // 2. create appraisal_result
        AppraisalResult appraisalResult = new AppraisalResult(supplier, appraisal, operator);
        genericDaoSupport.save(appraisalResult);
        
        // 3. create appraisal_result_item
        List<AppraisalTemplateItem> templateItems = appraisalItemTemplateDao.list(appraisal.getTemplate());
        for(AppraisalTemplateItem item : templateItems) {
            AppraisalResultItem AppraisalResultItem = new AppraisalResultItem(item, appraisal, appraisalResult, operator);
            genericDaoSupport.save(AppraisalResultItem);
        }
        
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#create(com.demo2do.fms.entity.vendor.Vendor, com.demo2do.fms.entity.appraisal.Appraisal, java.lang.Long)
     */
    public void create(Vendor vendor, Appraisal appraisal, Long operator) {
        
        // 1. valid supplier whether exists
        AppraisalResult existAppraisalResult = appraisalResultDao.load(appraisal, vendor.getId());
        if (existAppraisalResult != null) {
            throw BusinessException.newInstance("500", "供方'" + vendor.getName() + "'已存在本次绩效考核中");
        }
        
        // 2. create appraisal_result
        AppraisalResult appraisalResult = new AppraisalResult(vendor, appraisal, operator);
        genericDaoSupport.save(appraisalResult);
        
        // 3. create appraisal_result_item
        List<AppraisalTemplateItem> templateItems = appraisalItemTemplateDao.list(appraisal.getTemplate());
        for(AppraisalTemplateItem item : templateItems) {
            AppraisalResultItem AppraisalResultItem = new AppraisalResultItem(item, appraisal, appraisalResult, operator);
            genericDaoSupport.save(AppraisalResultItem);
        }
        
    }

    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#rate(java.util.List, com.demo2do.fms.entity.appraisal.AppraisalResult, com.demo2do.fms.admin.entity.security.Login)
     */
    public void rate(List<String> resultItems, AppraisalResult appraisalResult, Login login) {
        
        BigDecimal scoreTotal = BigDecimal.ZERO;
        BigDecimal originalScore = BigDecimal.ZERO;
        
        // 1. update result_item
        for(String resultItem : resultItems) {
            String[] item = StringUtils.split(resultItem, "|");
            AppraisalResultItem AppraisalResultItem = genericDaoSupport.load(AppraisalResultItem.class, Long.parseLong(item[0]));
            if(AppraisalResultItem != null) {
                
                BigDecimal score = new BigDecimal(item[1]);
                
                // 判断评分是否大于最高评分
                if(score.compareTo(AppraisalResultItem.getScore()) > 0) {
                    throw new BusinessException("评分不可大于最高上限！");
                }
                
                if (AppraisalResultItem.getRealScore() != null) {
                    originalScore = originalScore.add(AppraisalResultItem.getRealScore());
                }
                
                genericDaoSupport.update(AppraisalResultItem.rate(score, login.getId()));
                scoreTotal = scoreTotal.add(score);
                
            }
            
        }
        
        // 2. update appraisalResult
        genericDaoSupport.update(appraisalResult.rate(scoreTotal, login.getId()));
        
        // 3. update appraisal 
        Appraisal appraisal = appraisalResult.getAppraisal();
        genericDaoSupport.update(appraisal.rate(originalScore, scoreTotal));
    
    }

	/* (non-Javadoc)
	 * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#listByTarget(java.lang.String, java.util.Date, com.demo2do.fms.entity.appraisal.AppraisalType)
	 */
	public List<AppraisalResult> listByTarget(String supplierId, Date timeAgo, AppraisalType appraisalType) {

		return appraisalResultDao.listByTarget(supplierId, timeAgo, appraisalType);
	}
	
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.supplier.AppraisalResultService#delete(java.lang.Long, java.lang.Long)
     */
    public void delete(Long appraisalResultId, Long operator) {
        
        AppraisalResult appraisalResult = genericDaoSupport.load(AppraisalResult.class, appraisalResultId);
        
        List<AppraisalResultItem> appraisalResultItems = appraisalResultItemDao.list(appraisalResult);
        
        for (AppraisalResultItem appraisalResultItem : appraisalResultItems) {
            
            appraisalResultItem.delete(operator);
            
            genericDaoSupport.update(appraisalResultItem);
        }
        appraisalResult.delete(operator);
        
        genericDaoSupport.update(appraisalResult);
        
    }
    
}